Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Source defaults from the model instead of implicitly #2985

Merged
merged 3 commits into from
Sep 19, 2023
Merged

Conversation

rcoh
Copy link
Collaborator

@rcoh rcoh commented Sep 14, 2023

Motivation and Context

We weren't correctly computing defaults which lead to incorrect behavior when coupled with nullability.

Description

Minimal changeset to source defaults from the model. Other changes:

  • Unify enum parsing across client and server to always use from_str in protocol tests
  • Extract PrimitiveInstantiator from Instantiator so it can be used to instantiate defaults

Testing

  • regular codegen tests

Checklist

  • I have updated CHANGELOG.next.toml if I made changes to the smithy-rs codegen or runtime crates
  • I have updated CHANGELOG.next.toml if I made changes to the AWS SDK, generated SDK code, or SDK runtime crates

By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice.

@github-actions
Copy link

A new generated diff is ready to view.

A new doc preview is ready to view.

Copy link
Contributor

@ysaito1001 ysaito1001 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for adding a test to show what's supported now.

"json_token_iter" to smithyJson.resolve("deserialize::json_token_iter"),
)
}
is SimpleShape -> PrimitiveInstantiator(runtimeConfig, symbolProvider).instantiate(shape, data)(writer)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great SimpleShape reduces the multiple branches!

@github-actions
Copy link

A new generated diff is ready to view.

A new doc preview is ready to view.

@github-actions
Copy link

A new generated diff is ready to view.

A new doc preview is ready to view.

@@ -30,6 +30,11 @@ fun Writable.map(f: RustWriter.(Writable) -> Unit): Writable {
return writable { f(self) }
}

/** Returns Some(..arg) */
fun Writable.some(): Writable {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice.

@@ -102,6 +103,8 @@ sealed class Default {
* This symbol should use the Rust `std::default::Default` when unset
*/
object RustDefault : Default()

data class NonZeroDefault(val value: Node) : Default()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Docs would be nice.

Comment on lines 275 to 276
else -> { Default.NonZeroDefault(value)
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
else -> { Default.NonZeroDefault(value)
}
else -> Default.NonZeroDefault(value)

@@ -263,13 +268,21 @@ open class SymbolVisitor(

override fun memberShape(shape: MemberShape): Symbol {
val target = model.expectShape(shape.target)
val defaultValue = shape.getMemberTrait(model, DefaultTrait::class.java).orNull()?.let { trait ->
when (val value = trait.toNode()) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we have to distinguish the case where the user passes in a value to @default that happens to coincide with the default value for the type in Rust, from the case where it doesn't (NonZeroDefault)? Why can't we always set the value from the @default trait?

Generated client code would always use unwrap_or_else(default_value) instead of unwrap_or_default().

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • triggers clippy lint
  • causes a huge codegen diff
  • non-zero defaults are only allowed on simple shapes so it enables some simplification of generating defaults

val data = escape(arg.value).dq()
if (shape.hasTrait<EnumTrait>() || shape is EnumShape) {
val enumSymbol = symbolProvider.toSymbol(shape)
rust("$data.parse::<#T>().unwrap()", enumSymbol)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
rust("$data.parse::<#T>().unwrap()", enumSymbol)
rust("$data.parse::<#T>().expect("this is only used in tests")", enumSymbol)

@rcoh rcoh added this pull request to the merge queue Sep 19, 2023
@github-actions
Copy link

A new generated diff is ready to view.

A new doc preview is ready to view.

Merged via the queue into main with commit 9b0e3cf Sep 19, 2023
41 checks passed
@rcoh rcoh deleted the minimal-trait-defaults branch September 19, 2023 14:20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants